﻿Public Class HttpRequest
    Public Class Header
        Public Property Name As String
        Public Property Value As String

        Public Sub New()
        End Sub
        Public Sub New(name As String, value As String)
            Me.Name = name
            Me.Value = value
        End Sub
    End Class

    Public Enum RequestType
        [GET] = 1
        POST = 2
    End Enum

    Public Property Url As String
    Public Property Data As String
    Public Property Type As RequestType
    Public Property Headers As List(Of Header)
    Private Shared userAgent As String = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"

    Public Sub New()
        Me.Type = RequestType.GET
    End Sub
    Public Sub New(url As String)
        Me.New()
        Me.Url = url
    End Sub
    Public Sub New(url As String, data As String)
        Me.New(url)
        Me.Data = data
    End Sub
    Public Sub New(url As String, type As RequestType, data As String)
        Me.New(url, data)
        Me.Type = type
    End Sub
    Public Sub New(url As String, type As RequestType, data As String, headers As Header())
        Me.New(url, type, data, headers.ToList)
    End Sub
    Public Sub New(url As String, type As RequestType, data As String, headers As List(Of Header))
        Me.New(url, type, data)
        Me.Headers = headers
    End Sub

    Public Function Request() As String
        Return Request(Me.Url, Me.Type, Me.Data, Me.Headers)
    End Function

    Private Shared Function Item(headers As List(Of Header), name As String) As String
        Return headers.Find(Function(match) Trim(match.Name).Replace("-", "").ToLower = Trim(name).Replace("-", "").ToLower).Value
    End Function
    Private Shared Function Exists(headers As List(Of Header), name As String) As Boolean
        Return headers.Exists(Function(match) Trim(match.Name).Replace("-", "").ToLower = Trim(name).Replace("-", "").ToLower)
    End Function
    Private Shared Function EqualsTo(str1 As String, str2 As String, Optional comparisonType As StringComparison = StringComparison.CurrentCultureIgnoreCase) As Boolean
        Return str1.Replace("-", "").Equals(str2.Replace("-", ""), comparisonType)
    End Function
    Public Shared Function Request(url As String, type As RequestType, data As String, headers As List(Of Header)) As String
        If Trim(url) = "" Then Return ""
        If type = Nothing Then type = RequestType.GET

        If headers Is Nothing Then headers = New List(Of Header)
        If Not Exists(headers, "Accept") Then headers.Add(New Header("Accept", "*/*"))
        If Not Exists(headers, "UserAgent") Then headers.Add(New Header("UserAgent", userAgent))
        If Not Exists(headers, "Connection") Then headers.Add(New Header("Connection", "Keep-Alive"))

        url = Trim(url)
        data = Trim(data)
        If type = RequestType.GET AndAlso Trim(data) <> "" Then
            Dim trimChars = {"?"c, "&"c}
            url = url.TrimEnd(trimChars)
            data = data.TrimStart(trimChars)
            url &= If(url.Contains("?"), "&", "?") & data
        End If

        Net.ServicePointManager.Expect100Continue = False
        Dim webRequest As Net.HttpWebRequest = Net.WebRequest.Create(url)
        For Each header In headers
            If Net.WebHeaderCollection.IsRestricted(header.Name) Then
                If EqualsTo(header.Name, "Host") Then webRequest.Host = header.Value
                If EqualsTo(header.Name, "Accept") Then webRequest.Accept = header.Value
                If EqualsTo(header.Name, "Expect") Then webRequest.Expect = header.Value
                If EqualsTo(header.Name, "Referer") Then webRequest.Referer = header.Value
                If EqualsTo(header.Name, "Date") Then webRequest.Date = CDate(header.Value)
                If EqualsTo(header.Name, "User-Agent") Then webRequest.UserAgent = header.Value
                'If EqualsTo(header.Name, "Connection") Then webRequest.Connection = header.Value
                If EqualsTo(header.Name, "Content-type") Then webRequest.ContentType = header.Value
                If EqualsTo(header.Name, "If-Modified-Since") Then webRequest.IfModifiedSince = header.Value
                If EqualsTo(header.Name, "Content-Length") Then webRequest.ContentLength = CLng(header.Value)
                If EqualsTo(header.Name, "Transfer-Encoding") Then webRequest.TransferEncoding = header.Value
                'Range
                'Proxy-Connection
            Else
                webRequest.Headers.Add(header.Name, header.Value)
            End If
        Next
        webRequest.Method = type.ToString()

        If type = RequestType.POST Then
            webRequest.ContentType = "application/x-www-form-urlencoded"
            Dim dataByte = New Text.UTF32Encoding().GetBytes(data)
            webRequest.ContentLength = dataByte.Length
            Dim stream = webRequest.GetRequestStream()
            stream.Write(dataByte, 0, dataByte.Length)
            stream.Close()
        End If

        Dim reader As New IO.StreamReader(webRequest.GetResponse().GetResponseStream)
        Return reader.ReadToEnd
    End Function
End Class